package ru.averta.notes.service.search;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.morphology.english.EnglishAnalyzer;
import org.apache.lucene.morphology.russian.RussianAnalyzer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.averta.notes.other.UtilsCommon;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

/**
 * <code>MultiLangAnalyzer</code>
 *
 * @author: fedor.belov (fedor.belov@mail.ru)
 * Date: 30.05.11 0:31
 */

public final class MultiLangAnalyzer extends Analyzer {

    private static final Logger logger = LoggerFactory.getLogger(MultiLangAnalyzer.class);

    private static LanguageDetectService langService;

    private static Analyzer enAnalyzer;
    private static Analyzer ruAnalyzer;

    public MultiLangAnalyzer() {

    }

    @Override
    public TokenStream tokenStream(String s, Reader reader) {

        /** Хитрым способом обходим проблему одного чтения - http://stackoverflow.com/questions/6170881/java-how-can-i-read-reader-multiple-times */
        StringReader stringReader = UtilsCommon.toStringReader(reader);
        String stringValue = UtilsCommon.readerToString(stringReader);

        //Получаем аналайзер, парсим
        Analyzer analyzer = getAnalyzer(stringValue);
        return  analyzer.tokenStream(s, stringReader);
    }

    @Override
    public int getPositionIncrementGap(String fieldName) {
        //страница 141 (179) lucene in action
        //http://stackoverflow.com/questions/7532402/lucene-searches-on-2-field-values-as-single
        return 15;
    }

    public static Analyzer getAnalyzer(String s) {
        LanguageDetectService.Language lang = getLangService().detect(s);
        if(lang==LanguageDetectService.Language.RU) {
            logger.debug("Для текста {} используем русский analyzer", s);
            return getRuAnalyzer();
        } else if(lang==LanguageDetectService.Language.EN) {
            logger.debug("Для текста {} используем английский analyzer", s);
            return getEngAnalyzer();
        } else {
            return getRuAnalyzer(); //По-умолчанию парсим русским
        }
    }

    private static Analyzer getRuAnalyzer() {
        if (ruAnalyzer == null) {
            try {
                ruAnalyzer = new RussianAnalyzer();
            } catch (IOException e) {
                logger.error("Ошибка при получении русского analyzer'a", e);
            }
            /*ruAnalyzer = new WhitespaceAnalyzer();*/
        }

        return ruAnalyzer;
    }

    private static Analyzer getEngAnalyzer() {
        if (enAnalyzer == null) {
            try {
                enAnalyzer = new EnglishAnalyzer();
            } catch (IOException e) {
                logger.error("Ошибка при получении английского analyzer'a", e);
            }
            /*enAnalyzer = new WhitespaceAnalyzer();*/
        }

        return ruAnalyzer;
    }

    private static LanguageDetectService getLangService() {
        if(langService==null) langService = UtilsCommon.getBean(LanguageDetectService.class);
        return langService;
    }
}
